package com.min.gps.service;

/**
 * Created by Administrator on 2017/7/6 0006.
 */

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.min.gps.model.DataCode;
import com.min.gps.model.GPSInfo;
import com.min.gps.model.LoraInfo;
import com.min.gps.util.ByteUtils;
import com.min.gps.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreadServer {

    private int port = 1122;
    private ServerSocket serverSocket;
    private ExecutorService executorService;
    private final int POOL_SIZE = 10;
    Logger log = LogManager.getLogger(DataServer.class);

    public MultiThreadServer() throws IOException {
        serverSocket = new ServerSocket(port);
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
                .availableProcessors() * POOL_SIZE);
    }

    public void service() {
        while (true) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();
                executorService.execute(new Handler(socket));

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class Handler implements Runnable {
    Logger log = LogManager.getLogger(Handler.class);
    private boolean close = false; // 关闭连接标志位，true表示关闭，false表示连接
    public static final String CHARCODE = "utf-8";
    BackClient backClient = new BackClient();
    private Socket socket;

    public Handler(Socket socket) throws IOException {
        this.socket = socket;
    }

    public void run() {

        while (true) {//保持长连接
            if (socket != null) {
                DataInputStream input = null;
                DataOutputStream out = null;
                close = isServerClose(socket);//判断是否断开,心跳
                if (!close) {
                    try {
                        socket.setKeepAlive(true);
                        input = new DataInputStream(socket.getInputStream());
                        out = new DataOutputStream(socket.getOutputStream());
                        byte[] buff = new byte[1024];
                        input.read(buff);
                        int type = buff[6];
                        byte[] lengthData = new byte[2];//数据长度
                        System.arraycopy(buff, 1, lengthData, 0, 2);
                        byte[] cityID = new byte[2];//车辆ID
                        System.arraycopy(buff, 4, cityID, 0, 2);
                        int datalength = Integer.parseInt(ByteUtils.bytesToHexString(lengthData), 16);//字节数组转十进制
                        int crclength = datalength + 4;
                        byte[] crxData = new byte[crclength];//校验数据
                        System.arraycopy(buff, 0, crxData, 0, crclength);
                        byte[] Data = new byte[datalength - 3];//解析数据
                        System.arraycopy(buff, 7, Data, 0, Data.length);
                        byte[] cxcCode = new byte[2];
                        System.arraycopy(buff, crclength, cxcCode, 0, 2);
                        String checkCode = String.format("%04x", CRC16Util.calcCrc16(crxData)).toUpperCase();
                        if (ByteUtils.bytesToHexString(cxcCode).equals(checkCode)) {//crc16校验
                            if (type == 1) {//GPS数据解析
                                GPSInfo parseData = new GPSInfo();
                                String tempdata = new String(Data);
                                String gpsArray[] = tempdata.split(",");
                                parseData.setCityID(ByteUtils.bytesToHexString(cityID));
                                parseData.setSendTime(DateUtil.getNowDateTime());
                                parseData.setDataFormat(gpsArray[0]);
                                parseData.setStatus(gpsArray[2]);
                                parseData.setGPSTime(GpsUtil.posDate(gpsArray[9]) + GpsUtil.posTime(gpsArray[1]));
                                parseData.setLatitude(GpsUtil.hemisphere(gpsArray[4]) + GpsUtil.latitude(gpsArray[3]));
                                parseData.setLongitude(GpsUtil.hemisphere(gpsArray[6]) + GpsUtil.longitude(gpsArray[5]));
                                parseData.setSpeed(gpsArray[7]);
                                parseData.setHeading(gpsArray[8]);
                                parseData.setMagneticDeclination(gpsArray[10]);
                                parseData.setMagneticDirection(gpsArray[11]);
                                GPSService dataService = (GPSService) SpringContextUtil.getBean("GPSService");
                                dataService.save(parseData);
                                //gps数据解析后推送到web端
                                JSONObject result = new JSONObject();
                                result.put("data", JSON.toJSONString(parseData));
                                HttpRequestUtils.httpPost("http://localhost:9001/send", result, false);
                                //out.writeUTF(JSON.toJSONString(parseData));
                                // out.flush();
                            }
                            if (type == 2) {//Lora数据解析
                                List<DataCode> listCode = new ArrayList<>();
                                for (int i = 0; i < Data.length / 6; i++) {
                                    byte[] array = Arrays.copyOfRange(Data, 6 * i, 6 * i + 6);
                                    byte[] checkArray = new byte[5];
                                    System.arraycopy(array, 0, checkArray, 0, 5);
                                    byte[] ByteCode = new byte[3];
                                    System.arraycopy(array, 1, ByteCode, 0, 3);
                                    if (array[5] == ByteUtils.checkByte(checkArray)) {
                                        DataCode dataCode = new DataCode();
                                        dataCode.setByteCode(ByteUtils.bytesToHexString(ByteCode));
                                        listCode.add(dataCode);
                                    }
                                }
                                LoraInfo parseData = new LoraInfo();
                                parseData.setCityID(ByteUtils.bytesToHexString(cityID));
                                parseData.setSendTime(DateUtil.getNowDateTime());
                                parseData.setDataList(listCode);
                                LoraService dataService = (LoraService) SpringContextUtil.getBean("LoraService");
                                dataService.save(parseData);
                                //lora数据解析后通过socketClient推送到后端服务（断开需自动重连）
                                backClient.sendMessage(JSON.toJSONString(parseData));
                                // out.writeUTF(JSON.toJSONString(parseData));
                                //  out.flush();
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

    /**
     * 判断是否断开连接，断开返回true,没有返回false
     *
     * @param socket
     * @return
     */
    public Boolean isServerClose(Socket socket) {
        try {
            socket.sendUrgentData(0xFF);//发送1个字节的紧急数据，默认情况下，服务器端没有开启紧急数据处理，不影响正常通信
            return false;
        } catch (Exception se) {
            return true;
        }
    }
}